#pragma once

#include<iostream>
#include<pthread.h>
#include<vector>
#include<queue>
#include<unistd.h>
#include"Thread.hpp"
#include"Task.hpp"
#include"LockGuard.hpp"

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

const int n = 5;

template<class T>
class ThreadPool
{
public:
  ThreadPool(int num = n)
    :_num(num)
  {
    pthread_mutex_init(&_mutex,nullptr);
    pthread_cond_init(&_cond,nullptr);
  }
  
  void Wait()
  {
    pthread_cond_wait(&_cond,&_mutex);
  }

  void WakeUp()
  {
    pthread_cond_signal(&_cond);
  }

  pthread_mutex_t* GetMutex()//_mutex是局部变量
  {
    return &_mutex;
  }

  void push(const T& key)
  {
    LockGuard Lock(GetMutex());
    _task.push(key);
    WakeUp();  
  }
  
  void pop(T& key)
  {
    LockGuard Lock(GetMutex());
    while(_task.empty())
    {
      Wait();
    }
    key = _task.front();
    _task.pop();
  }

  static void* ThreadRoutine(void* args)
  {
    ThreadPool<T>* tp = static_cast<ThreadPool<T>*>(args);
    while(true)
    {
      T t;
      tp->pop(t);
      t();
      LockGuard Lock(&mutex);
      cout << "某个线程运行 : " << t.FormatRes() << endl;
    }
  }

  void init()
  {
    for(int i = 0; i < _num; ++i)
    {
      _threads.push_back(Thread(i,ThreadRoutine,this));
    }
  }

  void Start()
  {
    for(auto& thread : _threads)
    {
      thread.run();
    }
  }

  ~ThreadPool()
  {
    for(auto& thread : _threads)
    {
      thread.join();
    }
    pthread_mutex_destroy(&_mutex);
    pthread_cond_destroy(&_cond);
  }
private:
  vector<Thread> _threads;
  int _num;
  queue<T> _task;
  pthread_mutex_t _mutex;
  pthread_cond_t _cond;
};

